home *** CD-ROM | disk | FTP | other *** search
/ The PC-SIG Library 9 / The PC-SIG Library on CD ROM - Ninth Edition.iso / 001_100 / DISK0070 / DISK0070.ZIP / VPRINT.ASM < prev    next >
Assembly Source File  |  1983-02-13  |  8KB  |  230 lines

  1. ; PROGRAM VPRINT version 1.0
  2. ;      by Dave Whitman
  3. ;
  4. ; Redirects printer output to a specified disk file,
  5. ; providing a virtual printer.  Invoked from DOS by
  6. ; the command: VPRINT filespec
  7. ;
  8. ; Changes vector to BIOS printer routine to point
  9. ; to VPRINT code.  The VPRINT code is grafted onto
  10. ; DOS, and will not be overwritten by other programs.
  11. ;
  12. fcb            equ [5CH]   ;file control block
  13. name           equ [5DH]   ;name field of fcb
  14. name_length    equ 11      ;length of name field in fcb
  15. cur_block      equ [68H]   ;current block field
  16. current_rec    equ [7CH]   ;current record field
  17. record_size    equ [6AH]   ;record size field
  18. dta_length     equ 200H    ;length of internal disk buffer
  19. param_count    equ [80H]   ;contains # of chars in param area
  20. param_area     equ [81H]   ;PSP unformated param area
  21. dummy_dta      equ [80H]   ;leave dta set here on return
  22. cr             equ  0DH    ;ascii carriage return
  23. lf             equ  0AH    ;ascii line feed
  24. vector_offset  equ [005CH] ;offset part of interrupt vector 17H
  25. vector_segment equ [005EH] ;segment part of interrupt vector 17H
  26. printer_io     equ EFD2H   ;offset of BIOS routine
  27. ;
  28.        jmp init          ;branch around redirection code
  29. ;
  30. ;------------------------------------------------------
  31. ; This section of code will be grafted onto DOS.
  32. ; Calls to PRINTER_IO are redirected here, where
  33. ; they are converted to DOS sequential file writes.
  34. convert 
  35.          sti                    ;enable interupts
  36.          or ah,ah               ;request to print char?
  37.          jnz abort              ;abort if not
  38. ;
  39.          push dx                ;save state
  40.          push ds 
  41.          push cs
  42.          pop  ds                ;and establish addr.
  43.          mov char,al            ;save the char
  44. ;
  45.          cmp al,lf             ;is this a line feed?
  46.          je  exit              ;exit if so
  47. ;
  48.          call printchar        ;print the charactor
  49.          cmp  al,cr            ;was that a carriage return?
  50.          jne  exit             ;exit if not
  51.          mov al,lf             ;otherwise generate a line feed
  52.          call printchar        ;and send it
  53. ;
  54. exit     mov al,char           ;restore state
  55.          pop ds
  56.          pop dx
  57. ;
  58. ;=========================================================
  59. ; We have to return a status byte in AH.  The way I read
  60. ; Tech. Ref., to signal all ok we should send value 50H.
  61. ; However, a long DEBUG session showed that Easywriter 1.1
  62. ; expects to get 90H as the OK value.  I would interpret this
  63. ; as "printer busy", but we'll humor Easywriter.  
  64. ;=========================================================
  65. ;
  66. abort    mov ah,90H            ;move status = ok to AH
  67.          iret                  ;and return
  68. ;
  69. printchar proc near
  70.           push di
  71.           mov di,numchars      ;position in buffer for char
  72.  
  73.           mov offset(dta)[di],al ;mov char into buffer
  74. ;
  75.           inc di               ;update number of chars
  76.           mov numchars,di      ;and save it
  77. ;
  78.           cmp di,dta_length    ;is the buffer full?
  79.           jne pc-exit          ;exit if not
  80.           call dumpdta         ;otherwise dump it
  81. ;
  82. pc-exit   pop di
  83.           ret
  84.           endp
  85. ;
  86. dumpdta  proc near
  87.          push ax                       ;save state
  88.          push dx
  89. ;
  90.          mov ah,0FH                    ;open file
  91.          mov dx,offset(fcb)
  92.          int 21H
  93. ;
  94.          movw record_size,dta_length   ;set record size
  95.  
  96.          mov  ax,block_save            ;set fcb current block
  97.          mov  cur_block,ax
  98. ;
  99.          mov dx,offset(dta)            ;set disk transfer addr.
  100.          mov ah,1AH
  101.          int 21H
  102. ;
  103.          mov dx, offset(fcb)           ;write buffer to disk
  104.          mov ah,15H
  105.          int 21H
  106. ;
  107.          mov  ax, cur_block            ;save current block
  108.          mov  block_save,ax
  109. ;
  110.          mov  ax,1000H                 ;close file
  111.          mov  dx,offset(fcb)
  112.          int  21H
  113. ;
  114.          movw numchars,0000H           ;buffer is now empty
  115. ;
  116. ;======================================================
  117. ; Since we don't know where the DTA was set upon entry,
  118. ; we can't really restore the state of the machine.
  119. ; What we'll do is set up a dummy DTA for the caller to
  120. ; use, so it doesn't clobber our buffered data between calls.
  121. ; This is *NOT* foolproof, but seems to work OK with Easywriter.
  122. ;======================================================
  123. ;
  124.          mov dx,offset(dummy_dta)   ;set DTA to dummy block
  125.          mov ah,1AH
  126.          int 21H
  127.  
  128.          pop dx                     ;restore state
  129.          pop ax
  130.          ret                        ;and return
  131.          endp
  132. ;
  133. ;====================================================
  134. ; Data area for resident section
  135. ;====================================================
  136. char       db 00H           ;to save the char. passed
  137. numchars   db 00H,00H       ;word: # of chars in buffer
  138. block_save db 00H,00H       ;to save current block between calls
  139. dta        ds dta_length    ;internal data buffer
  140. ;
  141. ;===================================================
  142. ; Initialization section.  Does not become resident.
  143. ;===================================================
  144. init   cmpb name,' '              ;was a file specified?
  145.        jnz  a1                    ;skip if so
  146.  
  147.        cmpb param_count,00H       ;any param chars?
  148.        jz   default               ;skip if not
  149.        xor  ch,ch                 ;set up for scan
  150.        mov  cl,param_count
  151.        mov  di,offset(param_area)
  152.        mov  al,'/'                ;look for '/'
  153.        repnz                      ;scan to end or 1st match
  154.        scasb
  155. ;
  156.        jnz default                ;skip if not found
  157.        xorb [di],20H              ;guarantees upper case
  158. ;
  159.        cmpb [di],'N'              ;is it an N?
  160.        je   p_handler             ;if so, jump
  161. ;
  162. ;if no parameters decoded, just fall through
  163. ;and set up print file with default name
  164. ;
  165. default mov  si, offset(default_file_name)
  166.         mov  di, offset(name)
  167.         mov  cx, name_length
  168.         rep
  169.         movsb
  170. ;
  171. a1     mov dx, offset(fcb)         ;check if file exists
  172.        mov ah,11H
  173.        int 21H
  174. ;
  175.        test al,al                  ;file found?
  176.        jnz  a2                     ;skip if not
  177. ;
  178.        mov  dx, offset(err_msg_1)  ;otherwise print
  179.        mov  ah,09H                 ;error message
  180.        int 21H
  181.        int 20H                     ;and return to DOS
  182. ;
  183. a2     mov ah,16H                  ;create file
  184.        int 21H
  185. ;
  186.        test al,al                  ;file created?
  187.        jz   a3                     ;skip if so
  188.        mov  dx, offset(err_msg_2)  ;otherwise error
  189.        mov  ah, 09H
  190.        int  21H
  191.        int  20H
  192. ;
  193. a3     movw current_rec, 0         ;fill in fcb
  194. ;
  195.        mov ah,10H                  ;close file
  196.        mov dx, offset(fcb)
  197.        int 21H
  198. ;
  199.        mov ax,2517H                ;reset printer vector
  200.        mov dx, offset(convert)
  201.        int 21H
  202. ;
  203.        mov dx,offset(init)         ;point dx past resident code
  204.        int 27H                     ;end but stay resident
  205. ;===================================================================
  206. p_handler
  207. ;
  208.        mov ax,0000H              ;ext. addr. for vector
  209.        mov ds,ax
  210. ;
  211.        cmpw vector_offset,printer_io  ;already in BIOS?
  212.        je   p_exit                    ;exit if so
  213. ;
  214.        mov  ds,vector_segment    ;est. addr. in original vprint seg
  215.        call dumpdta              ;operates on buffer in original vprint
  216. ;
  217.        mov  ax,F000H             ;reset vector 17H to BIOS routine
  218.        mov  ds,ax                ;bios segment
  219.        mov  dx,printer_io        ;printer support routine
  220.        mov  ax,2517H
  221.        int 21H 
  222. ;
  223. p_exit int  20H                  ;return to DOS
  224. ;
  225. ;===================================================================
  226. err_msg_1  db 'File already exists!$'
  227. err_msg_2  db 'No room for file in directory.$'
  228. default_file_name db 'VIRTUAL PRN'
  229.